<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>图片懒加载</title>
</head>
<body>
  <script>
    let num = document.getElementsByTagName('img').length;
    let img = document.getElementsByTagName('img');
    let n = 0; // 存储图片加载到的位置，避免每次都从第一张图片开始遍历
    let isLoading = false;  // 是否当前容器/页面的图片加载完成
    let _clientHeight = document.documentElement.clientHeight;  // 可见区域高度
    let _scrollTop = document.documentElement.scrollTop || document.body.scrollTop;  //滚动条距离顶部高度
    
    // 监听窗口变化重新计算可视区域
    function computedClientHeight(){
      _clientHeight = document.documentElement.clientHeight; // 可见区域高度
    }
    // 页面载入完毕加载可视区域内的图片
    lazyLoad();
    function lazyLoad(){
      // 获取滚动条距离顶部高度
      isLoading = n >= num;
      _scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
      for(let i = n;i<num;i++){
        if(img[i].offsetTop<_clientHeight+_scrollTop){
          if(img[i].getAttribute('src')==''){
            img[i].src = img[i].getAttribute('data-src')
          }
          n = i + 1
        }
      }
    }

    /* 
     * 简单的节流函数throttle
     * @param
     * fun 要执行的函数
     * delay 延迟
     * time 在time时间内必须执行一次
     * flag 是否继续触发节流函数（根据需求自定义，这里就是相当加载完图片时不需要进行多余的执行--优化）
    */
   function throttle(func,wait,flag){
     let timeOut;
     return function(){
       if(flag) return;
       if(!timeOut){
         timeOut = setTimeout(() => {
           timeOut = null;
           func()
         }, wait);
       }
     }
   }
   /* 
    * 简单的防抖函数debounce
    * @param
    * fun 要执行的函数
    * wait 触发函数的时间间隔
   */
  function debounce(callback,delay){
    let timer;
    return function(arg){
      clearTimeout(timer);
      timer = setTimeout(() => {
        callback(arg)
      }, delay);
    }
  }
  
  // 使用了节流函数~实现性能较好的懒加载
  window.addEventListener('scroll',throttle(lazyLoad,100,isLoading))
  // 使用了防抖函数~优化不断触发的窗口变化
  window.addEventListener('resize',debounce(computedClientHeight,800))
  </script>
</body>
</html>